<!doctype html>
<html>
    <head>
        <title>HT 右键菜单手册</title>
        <meta charset="UTF-8">    
        <meta name="viewport" content="user-scalable=yes, width=1024">
        <style type="text/css"> 
            h1, h2, h3, h4, h5, h6, p, blockquote {
                margin: 0;
                padding: 0;
            }
            body {
                font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
                font-size: 13px;
                line-height: 18px;
                color: #737373;
                background-color: white; 
                margin: 10px 13px 10px 13px;
            }
            table {
                margin: 10px 0 15px 0;
                border-collapse: collapse;
            }
            td,th {	
                border: 1px solid #ddd;
                padding: 3px 10px;
            }
            th {
                padding: 5px 10px;	
            }
            a {
                color: #0069d6;
            }
            a:hover {
                color: #0050a3;
                text-decoration: none;
            }
            a img {
                border: none;
            }
            p {
                margin-bottom: 9px;
            }
            h1, h2, h3, h4, h5, h6 {
                color: #404040;
                line-height: 36px;
            }
            h1 {
                margin-bottom: 18px;
                font-size: 30px;
            }
            h2 {
                font-size: 24px;
            }
            h3 {
                font-size: 18px;
            }
            h4 {
                font-size: 16px;
            }
            h5 {
                font-size: 14px;
            }
            h6 {
                font-size: 13px;
            }
            hr {
                margin: 0 0 19px;
                border: 0;
                border-bottom: 1px solid #ccc;
            }
            blockquote {
                padding: 13px 13px 21px 15px;
                margin-bottom: 18px;
                font-family:georgia,serif;
                font-style: italic;
            }
            blockquote:before {
                content:"\201C";
                font-size:40px;
                margin-left:-10px;
                font-family:georgia,serif;
                color:#eee;
            }
            blockquote p {
                font-size: 14px;
                font-weight: 300;
                line-height: 18px;
                margin-bottom: 0;
                font-style: italic;
            }
            code, pre {
                font-family: Monaco, Andale Mono, Courier New, monospace;
            }
            code {
                background-color: #fee9cc;
                color: rgba(0, 0, 0, 0.75);
                padding: 1px 3px;
                font-size: 12px;
                border-radius: 3px;
            }
            pre {
                display: block;
                padding: 14px;
                margin: 0 0 18px;
                line-height: 16px;
                font-size: 11px;
                border: 1px solid #d9d9d9;
                white-space: pre-wrap;
                word-wrap: break-word;
            }
            pre code {
                background-color: #fff;
                color:#737373;
                font-size: 11px;
                padding: 0;
            }
            sup {
                font-size: 0.83em;
                vertical-align: super;
                line-height: 0;
            }
            * {
                -webkit-print-color-adjust: exact;
            }
            @media screen and (min-width: 914px) {
                body {
                    width: 854px;
                    margin:10px auto;
                }
            }
            @media print {
                body,code,pre code,h1,h2,h3,h4,h5,h6 {
                    color: black;
                }
                table, pre {
                    page-break-inside: avoid;
                }
            }                        
            iframe{
                width: 100%;
                border: 1px solid #34495E;
                margin: 0;                
            }            
            .logo{
                vertical-align: middle;
            }

        </style>        
        <script>
            function init() {
                var logoSrc = '',
                    logos = document.querySelectorAll('.logo'),
                    i = 0;
                for (; i < logos.length; i++) {
                    logos[i].src = logoSrc;
                }
                
                var iframes = document.querySelectorAll('iframe'),
                    func = function(){};
                for (i=0; i < iframes.length; i++) {
                    var iframe = iframes[i];
                    
                    // a small hack to make it work on android
                    iframe.ontouchstart = func;
                    
                    var div = document.createElement('div');
                    div.innerHTML = '<a href="' + iframe.src + '" target="_blank">独立运行→</a>';
                    iframe.parentNode.insertBefore(div, iframe);
                }   
            }
        </script>    
    </head>
    <body onload="init();">
        <a href="http://www.hightopo.com"><img class="logo"></a>HT 右键菜单手册
        <hr style="margin: 1px 0 20px 0">
<p>索引</p>

<ul><li><a href="#ref_description">概述</a></li><li><a href="#ref_dynamiccontextmenu1">动态菜单一</a></li><li><a href="#ref_dynamiccontextmenu2">动态菜单二</a></li><li><a href="#ref_contextmenucustomstyle">自定义菜单样式(一)</a></li><li><a href="#ref_contextmenucustomstyle2">自定义菜单样式(二:Win7风格)</a></li><li><a href="#ref_contextmenushowwithapi">调用API显示菜单</a></li></ul>

<hr/>

<div id="ref_description"></div>

<h3>概述</h3>

<p><code>ht.widget.ContextMenu</code>可以使任意<code>HTML</code>元素响应右键菜单，支持任意层次子菜单，图片<code>ICON</code>，<code>Check</code>多选，<code>Radio</code>单选，禁用菜单项以及自定义菜单样式，
在正式使用<code>API</code>之前，您的页面里应该引入相关的<code>js</code>文件：</p>

<pre><code>&lt;script src=&quot;ht.js&quot;&gt;&lt;/script&gt; &lt;!--先引入ht.js--&gt;
&lt;script src=&quot;key.js&quot;&gt;&lt;/script&gt; &lt;!--快捷键常量，可以按需引入--&gt;
&lt;script src=&quot;ht-contextmenu.js&quot;&gt;&lt;/script&gt;</code></pre>

<p><code>ContextMenu</code>提供的<code>API</code>如下：</p>

<ul><li><code>setItems(json)</code>设置菜单项，参数为<code>JSON</code>对象</li><li><code>addTo(dom)</code>参数为<code>HTML</code>元素，使其支持右键菜单</li><li><code>dispose()</code>销毁此右键菜单</li><li><code>show(x, y)</code>显示菜单,<code>x</code>,<code>y</code>为菜单显示页面在中的坐标</li><li><code>hide()</code>隐藏菜单</li><li><code>enableGlobalKey()</code> 启用全局快捷键，一旦启用此选项，菜单不再使用时需要显式调用<code>dispose()</code>销毁菜单</li><li><code>disableGlobalKey()</code> 禁用全局快捷键</li><li><code>beforeShow(event)</code>菜单显示之前被调用，可以重写此方法实现动态菜单功能</li><li><code>getItemByProperty(property, value)</code>查找属性名为<code>property</code>，值为<code>value</code>的菜单项，只返回第一个查找结果，注意：如果菜单显示时修改此查找结果，则菜单界面在下次显示时更新</li><li><code>afterShow(event)</code>菜单显示之后被调用</li><li><code>afterHide()</code>菜单隐藏之后被调用</li><li><code>isShowing()</code>检测菜单是否显示</li><li><code>setLabelMaxWidth(width)</code> 设置菜单中<code>label</code>的最大宽度，如果<code>label</code>过长会出现跑马灯效果</li><li><code>setVisibleFunc(function(item) {return true/false})</code> 设置可见过滤器</li></ul>

<p>右键菜单的内容由一个固定格式的<code>JSON</code>对象描述，包括菜单项的文字，图片以及相应的动作，下面的<code>JSON</code>描述了一个典型的右键菜单：</p>

<pre><code>var json = [
    {
        label: &quot;CheckMenuItems&quot;, //菜单文字
        items: [
            {
                label: &quot;Check1&quot;,
                icon: iconSrc, //菜单图片ICON
                type: &quot;check&quot; //可多选的菜单项
            },
            {
                label: &quot;Check2&quot;,
                icon: iconSrc,
                type: &quot;check&quot;
            },
            {
                label: &quot;Check3&quot;,
                icon: iconSrc,
                type: &quot;check&quot;,
                items: [
                    {
                        label: &quot;AAAA&quot;
                    },
                    {
                        label: &quot;BBBB&quot;
                    },
                    {
                        label: &quot;CCCC&quot;
                    },
                    {
                        label: &quot;DDDD&quot;
                    },
                    {
                        label: &quot;EEEE&quot;
                    },
                    //...
                ]
            }
        ]
    },
    {
        label: &quot;RadioMenuItems&quot;,
        items: [
            {
                label: &quot;Radio1&quot;,
                icon: iconSrc,
                type: &quot;radio&quot;, //单选菜单项
                groupId: 1 //菜单项分组
            },
            {
                label: &quot;Radio2&quot;,
                icon: iconSrc,
                type: &quot;radio&quot;,
                groupId: 1
            },
            {
                label: &quot;Radio3&quot;,
                icon: iconSrc,
                type: &quot;radio&quot;,
                groupId: 1
            }
        ]
    },
    &quot;separator&quot;, //分割线
    {
        label: &quot;Menu1(disabled)&quot;,
        disabled: true //禁用菜单项，可以是函数，由返回值决定是否禁用
    },   
    {
        label: &quot;Menu2&quot;,
        action: function(item, event) {
            alert(&quot;you clicked:&quot; + item.label + &quot;,this=&quot; + this);
        },
        scope: &quot;hello&quot; //指定回调函数中的this
    },
    {
        label: &quot;Menu3&quot;,
        icon: iconSrc,
        action: function(item) {
            alert(item.label);
        },
        items: [
            {
                label: &quot;Homepage&quot;, 
                href: &quot;http://www.hightopo.com&quot;, //超链到某个URL
                linkTarget: &quot;_blank&quot;, //超链目标，默认_self
                key: [Key.ctrl, Key.enter], //实际响应的快捷键
                suffix: &quot;Ctrl+Enter&quot;, //在菜单上显示的提示文字
                preventDefault: false //是否阻止快捷键默认的行为，默认为true
            },
            {
                label: &quot;submenu2&quot;,
                action: function(item) {
                    alert(item.label);
                }
            }
        ]
    }
    //...
];</code></pre>

<p>这个<code>JSON</code>对象渲染出来的右键菜单见下例：</p>

<p><iframe src="examples/example_base.html" style="height:200px"></iframe></p>

<pre><code>var contextmenu = new ht.widget.ContextMenu(json);
contextmenu.addTo(document.getElementById(&quot;div&quot;));</code></pre>

<p>如何定制更丰富的样式参考：<a href="#ref_contextmenucustomstyle">自定义菜单样式</a></p>

<div id="ref_dynamiccontextmenu1"></div>

<h3>动态菜单(一)</h3>

<p>某些情况下需要根据点击的内容决定右键菜单内容，例如在拓扑上根据点击的<code>Node</code>显示不同的右键菜单项，
我们可以在右键菜单显示出来之前做一些处理，参考下面的示例：</p>

<p><iframe src="examples/example_dynamic1.html" style="height:200px"></iframe></p>

<pre><code>var json1 = [{label: &quot;sendToTop&quot;},{label: &quot;sendToBottom&quot;}],
    json2 = [{label: &quot;Copy&quot;},{label: &quot;Paste&quot;}];

var graphView = new ht.graph.GraphView(),
    view = graphView.getView(),
    style = view.style,
    dataModel = graphView.dm();

//此处省略初始化Node的代码

//此处省略设置view样式的代码
document.body.appendChild(view);

var contextmenu = new ht.widget.ContextMenu();
//重写beforeShow，动态设置菜单项
contextmenu.beforeShow = function(e) {
    var data = graphView.getDataAt(e);
    if (data === node1) {
        this.setItems(json1);
    } else if (data === node2) {
        this.setItems(json2);
    } else {
        this.setItems(null); //参数为null不会阻止浏览器默认的右键菜单，如果要阻止，可将参数设为空数组：[]
    }
};
contextmenu.addTo(view);</code></pre>

<div id="ref_dynamiccontextmenu2"></div>

<h3>动态菜单(二)</h3>

<p>接下来我们用可见过滤器实现动态菜单：</p>

<p><iframe src="examples/example_dynamic2.html" style="height:200px"></iframe></p>

<pre><code>var contextmenu = new ht.widget.ContextMenu(json);
contextmenu.setVisibleFunc(function(item) {
    var data = graphView.sm().ld();
    if (data === node1) {
        if (item.fordata === 1) {
            return true;
        } else {
            return false;
        }
    } else if (data === node2) {
        if (item.fordata === 1) {
            return false;
        } else {
            return true;
        }
    }
});</code></pre>

<p>这个例子里我们把所有的菜单项全部加到右键菜单里，然后通过<code>visibleFunc</code>决定菜单项是否可见</p>

<div id="ref_contextmenucustomstyle"></div>

<h3>自定义菜单样式(一)</h3>

<p>右键菜单的样式可以使用全局的<code>htconfig</code>对象配置整体风格，可配置的参数如下：</p>

<ul><li><code>Default.contextMenuLabelFont</code> 文字字体，默认为<code>(isTouchable ? &#39;16&#39; : &#39;13&#39;) + &#39;px arial, sans-serif&#39;</code></li><li><code>Default.contextMenuLabelColor</code> 文字颜色，默认为 <code>#000</code></li><li><code>Default.contextMenuBackground</code> 背景颜色，默认为<code>#fff</code></li><li><code>Default.contextMenuDisabledLabelColor</code> 被禁用的菜单项的文字颜色，默认为<code>#888</code></li><li><code>Default.contextMenuHoverBackground</code> 鼠标划过的菜单项的背景颜色，默认为<code>#648BFE</code></li><li><code>Default.contextMenuHoverLabelColor</code> 鼠标划过的菜单项的文字颜色，默认为<code>#fff</code></li><li><code>Default.contextMenuSeparatorWidth</code> 分割线的宽度，默认为<code>1</code></li><li><code>Default.contextMenuSeparatorColor</code> 分割线的颜色，默认为<code>#E5E5E5</code></li><li><code>Default.contextMenuScrollerColor1</code> 滚动按钮渐变的开始颜色，默认为<code>#FDFDFD</code></li><li><code>Default.contextMenuScrollerColor2</code> 滚动按钮渐变的结束颜色，默认为<code>#D3D3D3</code>,</li><li><code>Default.contextMenuScrollerBorderColor</code> 滚动按钮的边框颜色，默认为<code>#C3C3C3</code></li><li><code>Default.contextMenuBorderColor</code> 菜单的边框颜色，默认为<code>#C3C3C3</code></li><li><code>Default.contextMenuShadowColor</code> 菜单阴影的颜色，默认为<code>rgba(128, 128, 128, 0.5)</code></li><li><code>Default.contextMenuCheckIcon</code> 多选按钮的图片，可以是图片<code>url</code>、<code>base64</code>字符串或是通过<code>ht.Default.setImage</code>注册是图片名</li><li><code>Default.contextMenuRadioIcon</code> 单选按钮的图片，可以是图片<code>url</code>、<code>base64</code>字符串或是通过<code>ht.Default.setImage</code>注册是图片名</li></ul>

<p>如下面的例子：</p>

<pre><code>&lt;script type=&quot;text/javascript&quot;&gt;
    htconfig = {
        Default: {
            contextMenuBackground: &#39;rgb(240,240,240)&#39;,
            contextMenuLabelColor: &#39;black&#39;,
            contextMenuHoverBackground: &#39;rgb(28,161,251)&#39;,
            contextMenuHoverLabelColor: &#39;black&#39;,
            contextMenuCheckIcon: &#39;checkIcon&#39;,
            contextMenuRadioIcon: &#39;radioIcon&#39;,
            contextMenuSeparatorColor: &#39;rgb(145,165,200)&#39;,
            contextMenuScrollerBorderColor: &#39;rgb(145,165,200)&#39;,
            contextMenuBorderColor: &#39;rgb(145,165,200)&#39;
        }
    }
&lt;/script&gt;</code></pre>

<p>经过渲染，菜单显示如下例所示：</p>

<p><iframe src="examples/example_customstyle.html" style="height:250px"></iframe></p>

<div id="ref_contextmenucustomstyle2"></div>

<h3>自定义菜单样式(二:Win7风格)</h3>

<p>右键菜单样式也可以通过<code>css</code>控制，由于右键菜单的内部采用行内样式，用户自定义样式需要<code>!important</code>关键字才能将其覆盖，看下面的例子：</p>

<pre><code>.ht-widget-contextmenu ul { /*ul是.menu-item的父节点*/
    background: url(&quot;data:image/png;...&quot;) repeat-y rgb(240, 240, 240) !important; /*背景色及竖分割线画到ul上*/
    background-position: -webkit-calc(1.4em + 4px) 0px !important; /*竖分割线的位置(safari6.x)*/
    background-position: calc(1.4em + 4px) 0px !important; /*竖分割线的位置*/
    border-radius: 0 !important;/*去掉圆角*/
}
.ht-widget-contextmenu .menu-item { /*菜单项相关样式*/
    background: rgba(0,0,0,0) !important; /*背景色改为透明，显示ul的背景*/
    color: black !important; /*文字颜色*/
    border: 1px solid rgba(0,0,0,0) !important; /*透明边框*/
    border-radius: 2px !important; /*圆角*/
    margin: 3px 2px !important; /*设置margin*/
}
.ht-widget-contextmenu .menu-item.menu-item-hover {
    /*鼠标滑过菜单项时，设置半透明的渐变背景色*/
    background: -webkit-linear-gradient(top, rgba(193,222,255,0.2),rgba(193,222,255,0.4)) !important;
    background: linear-gradient(to bottom, rgba(193,222,255,0.2),rgba(193,222,255,0.4)) !important;
    color: black !important;
    border: 1px solid rgb(183,212,246) !important;
}
.ht-widget-contextmenu .menu-item.disabled {  /*自定义已禁用菜单项的背景色和文字颜色*/
    color: #888 !important;
    background: rgba(0,0,0,0) !important;
}
.ht-widget-contextmenu .menu-item.disabled.menu-item-hover { /*自定义鼠标滑过已禁用菜单项时，菜单项的背景色,文字颜色及边框*/
    color: #888 !important;
    background: rgba(0,0,0,0) !important;
    border: 1px solid rgba(0,0,0,0) !important;
}
.ht-widget-contextmenu .prefix {
    margin-right: 0.8em !important; /*设置菜单项前缀和内容之间的距离*/
}
.ht-widget-contextmenu .suffix {
    margin-left: 3em !important; /*设置菜单项后缀和内容之间的距离*/
    margin-right: 1em !important; /*设置菜单项后缀和边缘之间的距离*/
}
.ht-widget-contextmenu .separator { /*分割条样式*/
    margin-left: -webkit-calc(1.4em + 5px) !important;
    margin-left: calc(1.4em + 5px) !important;
    height: 2px !important;
    background-image: -webkit-linear-gradient(top, rgb(226,226,226), rgb(226,226,226) 50%,rgb(252,252,252) 50%,rgb(252,252,252)) !important;
    background-image: linear-gradient(to bottom, rgb(226,226,226), rgb(226,226,226) 50%,rgb(252,252,252) 50%,rgb(252,252,252)) !important;
}</code></pre>

<p>注意菜单项(<code>.menu-item</code>)的结构：</p>

<p><img src=""></p>

<p>其中<code>prefix</code>和<code>suffix</code>有对应的样式类名，我们可以通过修改它们设置菜单项内部元素之间的间距。</p>

<p>效果如下：</p>

<p><iframe src="examples/example_customstyle2.html" style="height:250px"></iframe></p>

<div id="ref_contextmenushowwithapi"></div>

<h3>调用API显示菜单</h3>

<p>通常菜单通过右键触发显示即可，除此之外，<code>ContextMenu</code>也支持通过<code>API</code>控制显示和隐藏：</p>

<p><iframe src="examples/example_showwithapi.html" style="height:350px"></iframe></p>

<pre><code>//显示菜单
function show() {
    var x = parseInt(document.getElementById(&quot;menux&quot;).value),
        y = parseInt(document.getElementById(&quot;menuy&quot;).value);
    if (!isNaN(x) &amp;&amp; !isNaN(y)) {
        contextmenu.show(x,y);
    }
}
//隐藏菜单
function hide() {
    contextmenu.hide();
}</code></pre>    <hr id="contact" style="margin: 20px 0 1px 0">
    <a href="http://www.hightopo.com"><img class="logo"></a>欢迎交流 <a href="mailto:service@hightopo.com">service@hightopo.com</a>
</body>
</html>
